<template>
  <div id="yc-form">
    <el-scrollbar style="height:100%;">
      <el-form ref='form' :model="model" v-bind="formSetting" :rules='rulesFromSetting' v-loading="loading"
        :class="formSetting.class">
        <template v-if="formSetting.useLayout">
          <el-row v-bind="formSetting.row">
            <template v-for="(item,index) in itemSetting">
              <el-col :key='index' v-if="item.visible" v-bind='item.col'>
                <el-form-item class="form-item_label" :title="item.title" :label='item.title' :prop='item.prop'>
                  <div style="width:100%"  :ref="`editCell_${index}`" :is="handleEditableCellType(item)"
                    :edit-mode="editMode" @change="handleIsMultipleSelect(item)?$forceUpdate():handleChange"
                    v-bind="item" v-model='model[item.prop]'>
                      <template v-if="handleIsSelect(item) || handleIsMultipleSelect(item)">
                        <el-option v-for="(_item) in item.options" :key="_item.value" :label="_item.label"
                          :value="_item.value"></el-option>
                      </template>
                      <template v-else-if="handleIsRadioGroup(item)">
                        <el-radio v-for="(_item) in item.options" :key="_item.value" :label="_item.value">
                          {{_item.label}}</el-radio>
                      </template>
                      <template v-else-if="handleIsButton(item)">
                        {{item.label}}
                      </template>
                      <template v-else-if="handleIsButtonGroup(item)">
                        <el-button v-for="(btn,i) in item.options" @click="btn.click" :key="i" :type="btn.type">
                          {{btn.label}}</el-button>
                      </template>
                  </div>
                </el-form-item>
              </el-col>
            </template>
          </el-row>
        </template>
        <template v-else>
          <template v-for="(item,index) in itemSetting">
            <el-form-item :key='index' v-if="item.visible" :style="item.style" class="form-item_label"
              :title="item.title" :label='item.title' :prop='item.prop'>
              <div style="width:100%" :ref="`editCell_${index}`" :is="handleEditableCellType(item)"
                :edit-mode="editMode" @change="handleIsMultipleSelect(item)?$forceUpdate():handleChange" v-bind="item"
                v-on="item" v-model='model[item.prop]'>
                  <template v-if="handleIsSelect(item) || handleIsMultipleSelect(item)">
                    <el-option v-for="(_item) in item.options" :key="_item.value" :label="_item.label"
                      :value="_item.value"></el-option>
                  </template>
                  <template v-else-if="handleIsRadioGroup(item)">
                    <el-radio v-for="(_item) in item.options" :key="_item.value" :label="_item.value">{{_item.label}}
                    </el-radio>
                  </template>
                  <template v-else-if="handleIsButton(item)">
                    {{item.label}}
                  </template>
                  <template v-else-if="handleIsButtonGroup(item)">
                    <el-button v-for="(btn,i) in item.options" @click="btn.click" :key="i" :type="btn.type">
                      {{btn.label}}</el-button>
                  </template>
              </div>
            </el-form-item>
          </template>
        </template>
      </el-form>
    </el-scrollbar>
  </div>
</template>

<script>
import { initField, getFieldType, isSelect, isButton, isButtonGroup, isRadioGroup, isMultipleSelect } from './field'
import _ from 'lodash'

export default {
  name: 'yc-form',
  componentName: 'yc-form',
  props: {
    value: {
      type: [String, Object, Array]
    },
    itemSetting: {
      type: Array,
      required: true,
      default: function () {
        return []
      }
    },
    setting: {
      type: Object,
      default: function () {
        return {}
      }
    },
    loading: {
      type: Boolean,
      default: false
    },
    editMode: {
      type: Boolean,
      default: true
    }
  },
  data () {
    return {
      defaultSetting: {
        useLayout: false,
        labelWidth: '100px',
        size: 'mini',
        inline: false,
        labelPosition: 'right',
        class: 'is-thin',
        row: {
          gutter: 0
        }
      }
    }
  },
  computed: {
    model: {
      get () {
        return this.value
      },
      set (val) {
        this.$emit('input', val)
      }
    },
    // 根据表单设置计算出校验规规则
    rulesFromSetting () {
      return _.fromPairs(this.itemSetting.filter(item => item.rule).map(item => [item.prop, item.rule]))
    },
    // 根据表单设置计算出表单默认值
    defaultModelFromSetting () {
      return _.fromPairs(this.itemSetting.filter(item => item.default !== undefined).map(item => [item.prop, item.default]))
    },
    formSetting () {
      return _.merge(this.defaultSetting, this.setting)
    }
  },
  watch: {
    itemSetting () {
      this.$nextTick(() => {
        this.clearValidate()
        this.initColumnsConfig(this.itemSetting)
      })
    }
  },
  methods: {
    /**
     * @description 初始化配置
     * */
    initColumnsConfig (columns) {
      columns.forEach((item, index) => {
        initField(item)
      })
    },
    restForm (restDefault) {
      this.resetFields()
      if (restDefault) { this.$set(this, 'model', _.cloneDeep(this.defaultModelFromSetting)) }
    },
    /**
     * @description 默认值
     * */
    initDefaultValue () {
      if (JSON.stringify(this.model) === '{}' || this.model === null) {
        this.$set(this, 'model', _.cloneDeep(this.defaultModelFromSetting))
      }
    },
    /**
     * @description 设置属性
     * */
    modelSet (keyname = '', value = '') {
      this.$set(this.model, keyname, value)
    },
    /**
     * @description 设置属性
     * */
    modelBind (value = '') {
      this.$set(this, 'model', value)
    },
    /**
     * @description 清空表单校验
     */
    clearValidate () {
      this.$refs.form.clearValidate()
    },
    /**
     * @description 重置表单
     */
    resetFields () {
      this.$refs.form.resetFields()
    },
    /**
     * @description 表单校验
     */
    validate (result) {
      this.$refs.form.validate((valid) => {
        result.valid = valid
      })
    },
    /**
     * @description 获取类型
    * */
    handleEditableCellType (item) {
      return getFieldType(item)
    },
    /**
    * @description 是否选择器
     **/
    handleIsSelect (item) {
      return isSelect(item.name)
    },
    /**
    * @description 是否多选择器
     **/
    handleIsMultipleSelect (item) {
      return isMultipleSelect(item.name) || item.name === 'dict-select'
    },
    /**
    * @description 是否按钮
     **/
    handleIsButton (item) {
      return isButton(item.name)
    },
    /**
    * @description 是否按钮组
     **/
    handleIsButtonGroup (item) {
      return isButtonGroup(item.name)
    },
    /**
    * @description 是否单选组
     **/
    handleIsRadioGroup (item) {
      return isRadioGroup(item.name)
    },
    handleChange (val) {

    }
  },
  created () {
    this.$on('restForm', this.restForm)
    this.$on('validate', this.validate)
    this.initDefaultValue()
  },
  mounted () {
    this.resetFields()
  }
}
</script>

<style lang='scss'>
#yc-form {
  height: 100%;
  .el-scrollbar .el-scrollbar__wrap {
    overflow-x: hidden;
    margin-bottom: 0px !important;
    .el-scrollbar__view {
      height: 100%;
    }
  }
  .form-item_label > label {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}
</style>
